package Chat;

/*
 * Author: JacksonCoder
 * FileName: ChatServer
 * Version: 1.0.0
 * Date: 2025/5/7
 */

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.text.SimpleDateFormat;

public class ChatServerHandler extends ChannelInboundHandlerAdapter {

    // GlobalEventExecutor.INSTANCE 是全局的事件执行器，是一个单例
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 当客户端连接服务器就会触发该方法
     *
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        // 将该客户加入聊天的信息推送给其他的在线的客户端
        // 该方法会将 channelGroup 中的所有 channel 遍历，并发送消息
        channelGroup.writeAndFlush("[ 客户端 ]" + channel.remoteAddress() + " 上线了 " + sdf.format(new java.util.Date()) + "\n");
        // 当前的 channel 加入到 channelGroup
        channelGroup.add(channel);
        System.out.println(ctx.channel().remoteAddress() + " 上线了 " + "\n");

        /**
         *   ByteBuf buf = Unpooled.copiedBuffer("HelloServer".getBytes(CharsetUtil.UTF_8));
         *   ctx.writeAndFlush(buf);
         */
    }

    /**
     * 读取客户端发送的数据
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // 获取当前 channel
        Channel channel = ctx.channel();
        // 这时我们遍历 channelGroup， 根据不同的情况， 回复不同的消息
        channelGroup.forEach(ch -> {
            if (channel != ch) { // 不是当前的 channel 转发消息
                ch.writeAndFlush("[ 客户端 ]" + channel.remoteAddress() + " 发送了消息： " + msg + "\b");
            } else {
                ch.writeAndFlush("[ 自己 ] 发送了消息： " + msg + "\n");
            }
        });

        /**
         // Channel channel = ctx.channel();
         // ChannelPipeline pipeline = ctx.pipeline(); // 本质是一个双向链表, 出栈入栈
         // 将 msg 转成一个 ByteBuf， 类似 NIO 的 ByteBuffer
         ByteBuf buf = (ByteBuf) msg;
         System.out.println("收到客户端的消息: " + buf.toString(CharsetUtil.UTF_8));
         */
    }

    /**
     * 表示客户端不活动了下线了
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 打印异常信息
        cause.printStackTrace();
        // 向所有客户端广播异常信息
        channelGroup.writeAndFlush("[服务器] " + ctx.channel().remoteAddress() + " 出现异常：" + cause.getMessage() + "\n");
        // 关闭出现异常的通道
        ctx.close();
        // 可以选择将异常传递给下一个处理器，但在这里我们已经处理了，所以不需要再传递
        // ctx.fireExceptionCaught(cause);
    }

}
